package org.one.stone.soup.grfxML.ui;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;

import javax.swing.JComponent;

import org.one.stone.soup.grfx.ImageFactory;
import org.one.stone.soup.grfxML.DataKey;
import org.one.stone.soup.grfxML.GrfxMLEngine;
import org.one.stone.soup.grfxML.GrfxMLLoader;
import org.one.stone.soup.grfxML.GrfxMLProcessor;
import org.one.stone.soup.grfxML.GrfxMLView;
import org.one.stone.soup.mjdb.data.field.LockException;
  /*
 * Copyright 2000-2001 Wet-Wired.com Ltd.,
 * Portsmouth England
 * All rights reserved.
 */

  /*
 * Copyright 2000-2001 Wet-Wired.com Ltd.,
 * Portsmouth England
 * All rights reserved.
 */

/**
	*
	* @author Nik Cross
*/
public class GrfxMLJComponent extends JComponent implements GrfxMLView,MouseListener,MouseMotionListener,KeyListener{

	private ImageObserver observer;

	private GrfxMLEngine controller;

	private boolean offscreenReady=false;
	private boolean drawBorder = true;
	
	private boolean drawing=false;
	private int frameNumber;

	private boolean waitingForSnapshot = false;
	private Image renderedImage;

	private Image WAIT;

	private int width;
	private int height;
public GrfxMLJComponent(GrfxMLEngine controller,Container owner,int width,int height) {
	super();

	WAIT = ImageFactory.loadImage("jar://resources/wait.png");

	observer = owner;
	this.controller = controller;

	addKeyListener(this);
	addMouseListener(this);
	addMouseMotionListener(this);

	this.width=width;
	this.height=height;

	setBackground(Color.cyan);

	setSize(width,height);
}
public void destroy() {}
/**
 *
 */
public Dimension getMaximumSize()
{
	return getPreferredSize();
}
/**
 *
 */
public Dimension getMinimumSize()
{
	return getPreferredSize();
}
/**
 *
 */
public Dimension getPreferredSize()
{
	Dimension d = new Dimension(width,height);

	return d;
}
/**
 *
 */
public Dimension getSize()
{
	return getPreferredSize();
}
public void keyPressed(KeyEvent k) {

 try{

	int kv = k.getKeyCode();

	if(kv == KeyEvent.VK_CONTROL)
		DataKey.ctrl=true;

	if(kv == KeyEvent.VK_ALT)
		DataKey.alt=true;

	if( (int)k.getKeyChar()<33 )
		DataKey.ctrl=true;

	if(kv == KeyEvent.VK_SHIFT)
		DataKey.shift=true;

	//System.out.println("kc="+k.getKeyCode()+"kv="+((int)k.getKeyChar()));

	switch(kv)
	{
		case KeyEvent.VK_F1:
			DataKey.fn[0]=true;
			break;
		case KeyEvent.VK_F2:
			DataKey.fn[1]=true;
			break;
		case KeyEvent.VK_F3:
			DataKey.fn[2]=true;
			break;
		case KeyEvent.VK_F4:
			DataKey.fn[3]=true;
			break;
		case KeyEvent.VK_F5:
			DataKey.fn[4]=true;
			break;
		case KeyEvent.VK_F6:
			DataKey.fn[5]=true;
			break;
		case KeyEvent.VK_F7:
			DataKey.fn[6]=true;
			break;
		case KeyEvent.VK_F8:
			DataKey.fn[7]=true;
			break;
		case KeyEvent.VK_F9:
			DataKey.fn[8]=true;
			break;
		case KeyEvent.VK_F10:
			DataKey.fn[9]=true;
			break;
		case KeyEvent.VK_F11:
			DataKey.fn[10]=true;
			controller.getAPI().sendCommand("View Fullscreen");
			break;
		case KeyEvent.VK_F12:
			DataKey.fn[11]=true;
			break;
	}

	if(kv<255)
	{
		DataKey.kbd[kv]=true;
		controller.getAPI().getKey().lastKeyPressed.setValue(
			controller.getAPI().getKey().currentKeyPressed.getValue(),
			this
		);
		controller.getAPI().getKey().currentKeyPressed.setValue( kv,this );

		if(kv>31 || kv==8 || kv==9 || kv==10)
		{
			controller.getAPI().getKey().keyBuffer.append(k.getKeyChar());
		}
	}
 }catch(LockException le){}//dummy catch

}
public void keyReleased(KeyEvent k) {}

public void mouseDragged(MouseEvent e) {
	MouseEvent newE = new MouseEvent(
		this,
		MouseEvent.MOUSE_MOVED,
		e.getWhen(),
		e.getModifiers(),
		e.getX(),
		e.getY(),
		e.getClickCount(),
		e.isPopupTrigger()
		);
	mouseMoved(newE);
}
public void mouseMoved(MouseEvent e) {

	storeMouseEvent(e);
}
public void mousePressed(MouseEvent e) {
	storeMouseEvent( e );
	this.requestFocus();
}
public void mouseReleased(MouseEvent e) {

	storeMouseEvent( e );
}
public void paint(Graphics grfx) {
 try{
	drawing = true;

//----- Gernerate offscreen buffers at startup-----
	if(offscreenReady==false)
	{
		//int width=getSize().width;
		//int height=getSize().height;

		if(width==0)
			width=1;
		if(height==0)
			height=1;

		setBackground(GrfxMLProcessor.getColorFor(controller.getAPI().getBase().getSETTINGS().getBackgroundColor()));
		
		offscreenReady=true;

		this.doLayout();
	}
//-------------------------------------------------

	Graphics realGrfx = grfx;
	if(waitingForSnapshot)
	{
		if(renderedImage==null)
		{
			renderedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
		}
		grfx = renderedImage.getGraphics();
	}
	
	if(grfx instanceof Graphics2D)
	{
		if(controller.getAPI().getBase().getSETTINGS().getAntialias().getValue()==true)
		{
			((Graphics2D)grfx).setRenderingHint( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON );
		}
	}
	
	if( !GrfxMLLoader.isLoading(controller) )
	{
	    controller.process();
	    
   		grfx.setColor(GrfxMLProcessor.getColorFor(controller.getAPI().getBase().getSETTINGS().getBackgroundColor()));
   		grfx.fillRect(controller.getOffsetX(),controller.getOffsetY(),width,height);

   		controller.drawBackground(grfx);
		
		// Draw the grfxML model
		controller.draw(grfx);
		grfx.setColor(Color.BLACK);
		if(drawBorder==true && !waitingForSnapshot)
		{
			grfx.drawRect(0,0,width-1,height-1);	    
		}
			
		//renderedImage = preImg;
	    
	    controller.resetChanged();
	}
	else
	{
		grfx.drawImage(WAIT,4,4,observer);
	}

	if(waitingForSnapshot && renderedImage!=null)
	{
		realGrfx.drawImage(renderedImage,0,0,observer);
		grfx = realGrfx;
		waitingForSnapshot=false;
	}
	
	drawing = false;

 } catch(Exception e)
 {
	e.printStackTrace();
 	if(controller.getAPI().debugOn()) e.printStackTrace();
 }
 
 	super.paint(grfx);
 
 	frameNumber++;
}
public void setSize(int width, int height)
{

	super.setSize(width,height);

	this.width = width;
	this.height = height;

	if(controller.getAPI().debugOn()) System.out.println("Panel set. width:"+width+" height:"+height);
}
/**
 *
 * @param e java.awt.event.MouseEvent
 */
public void storeMouseEvent(MouseEvent e)
{
	controller.getAPI().getBase().getMOUSE().addEvent(e);
}
public void update(Graphics grfx) {
	paint(grfx);
}
	public Image createImage() {
		return createImage(getWidth(),getHeight());
	}
	/* (non-Javadoc)
	 * @see org.one.stone.soup.grfxML.GrfxMLView#getBackgroundImage()
	 */
	public Image getBackgroundImage() {
		//return bImg;
	    return null;
	}
	/* (non-Javadoc)
	 * @see org.one.stone.soup.grfxML.GrfxMLView#getPreImage()
	 */
	public Image getPreImage() {
		waitingForSnapshot=true;
		while(waitingForSnapshot)
		{
			try{ Thread.sleep(3); }catch(Exception e){}
		}
		return renderedImage;
	}

	public GrfxMLEngine getEngine()
	{
		return controller;
	}
	/* (non-Javadoc)
	 * @see org.one.stone.soup.grfxML.GrfxMLView#inFocus()
	 */
	public boolean inFocus() {
		// TODO Auto-generated method stub
		return true;
	}
	public boolean isDrawing() {
		return drawing;
	}
	/* (non-Javadoc)
	 * @see org.one.stone.soup.grfxML.GrfxMLView#setBackgroundImage(java.awt.Image)
	 */
	public void setBackgroundImage(Image backgroundImage) {
		//bImg = backgroundImage;
	}
	/* (non-Javadoc)
	 * @see org.one.stone.soup.grfxML.GrfxMLView#setOffscreenReady(boolean)
	 */
	public void setOffscreenReady(boolean state) {
		offscreenReady = state;
	}
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
	 */
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
	}
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
	 */
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
	}
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
	 */
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
	}
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
	 */
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
	}

	public void draw()
	{
		int startFrameNumber = frameNumber;
		long start = System.currentTimeMillis();
		this.repaint(1);
		
		while(startFrameNumber == frameNumber)
		{
			try{Thread.sleep(3);}catch(Exception e){}
		}
		//System.out.println(System.currentTimeMillis()-start);
	}
	public void setDrawBorder(boolean drawBorder) {
		this.drawBorder = drawBorder;
	}

}
